package com.robotic.sensor.service.impl;

import java.util.List;
import java.util.Date;
import java.math.BigDecimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.robotic.common.utils.DateUtils;
import com.robotic.common.utils.StringUtils;
import com.robotic.sensor.mapper.SensorDataMapper;
import com.robotic.sensor.domain.SensorData;
import com.robotic.sensor.domain.RegionStandard;
import com.robotic.sensor.service.ISensorDataService;
import com.robotic.sensor.service.IRegionStandardService;
import com.robotic.sensor.service.SensorDataJudgementService;

/**
 * 传感器数据Service业务层处理
 * 
 * @author robotic
 * @date 2024-01-20
 */
@Service
public class SensorDataServiceImpl implements ISensorDataService
{
    private static final Logger log = LoggerFactory.getLogger(SensorDataServiceImpl.class);

    @Autowired
    private SensorDataMapper sensorDataMapper;

    @Autowired
    private IRegionStandardService regionStandardService;

    @Autowired
    private SensorDataJudgementService sensorDataJudgementService;

    /**
     * 查询传感器数据
     * 
     * @param id 传感器数据主键
     * @return 传感器数据
     */
    @Override
    public SensorData selectSensorDataById(Long id)
    {
        return sensorDataMapper.selectSensorDataById(id);
    }

    /**
     * 查询传感器数据列表
     * 
     * @param sensorData 传感器数据
     * @return 传感器数据
     */
    @Override
    public List<SensorData> selectSensorDataList(SensorData sensorData)
    {
        return sensorDataMapper.selectSensorDataList(sensorData);
    }

    /**
     * 根据区域代码查询传感器数据
     * 
     * @param regionCode 区域代码
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectSensorDataByRegionCode(String regionCode)
    {
        return sensorDataMapper.selectSensorDataByRegionCode(regionCode);
    }

    /**
     * 根据传感器类型查询传感器数据
     * 
     * @param sensorType 传感器类型
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectSensorDataBySensorType(String sensorType)
    {
        return sensorDataMapper.selectSensorDataBySensorType(sensorType);
    }

    /**
     * 根据机器人ID查询传感器数据
     * 
     * @param robotId 机器人ID
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectSensorDataByRobotId(String robotId)
    {
        return sensorDataMapper.selectSensorDataByRobotId(robotId);
    }

    /**
     * 根据任务ID查询传感器数据
     * 
     * @param taskId 任务ID
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectSensorDataByTaskId(String taskId)
    {
        return sensorDataMapper.selectSensorDataByTaskId(taskId);
    }

    /**
     * 查询异常传感器数据（非标准数据）
     * 
     * @param regionCode 区域代码（可选）
     * @param sensorType 传感器类型（可选）
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectAbnormalSensorData(String regionCode, String sensorType)
    {
        return sensorDataMapper.selectAbnormalSensorData(regionCode, sensorType);
    }

    /**
     * 查询未处理的异常传感器数据
     * 
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectUnhandledAbnormalSensorData()
    {
        return sensorDataMapper.selectUnhandledAbnormalSensorData();
    }

    /**
     * 查询危险级别的传感器数据
     * 
     * @param regionCode 区域代码（可选）
     * @param sensorType 传感器类型（可选）
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectDangerSensorData(String regionCode, String sensorType)
    {
        return sensorDataMapper.selectDangerSensorData(regionCode, sensorType);
    }

    /**
     * 根据时间范围查询传感器数据
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param regionCode 区域代码（可选）
     * @param sensorType 传感器类型（可选）
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectSensorDataByTimeRange(Date startTime, Date endTime, String regionCode, String sensorType)
    {
        return sensorDataMapper.selectSensorDataByTimeRange(startTime, endTime, regionCode, sensorType);
    }

    /**
     * 查询最新的传感器数据
     * 
     * @param regionCode 区域代码
     * @param sensorType 传感器类型
     * @param limit 限制条数
     * @return 传感器数据集合
     */
    @Override
    public List<SensorData> selectLatestSensorData(String regionCode, String sensorType, Integer limit)
    {
        return sensorDataMapper.selectLatestSensorData(regionCode, sensorType, limit);
    }

    /**
     * 统计传感器数据数量
     * 
     * @param regionCode 区域代码（可选）
     * @param sensorType 传感器类型（可选）
     * @param detectStatus 检测状态（可选）
     * @return 数据数量
     */
    @Override
    public Long countSensorData(String regionCode, String sensorType, String detectStatus)
    {
        return sensorDataMapper.countSensorData(regionCode, sensorType, detectStatus);
    }

    /**
     * 新增传感器数据
     * 
     * @param sensorData 传感器数据
     * @return 结果
     */
    @Override
    public int insertSensorData(SensorData sensorData)
    {
        sensorData.setCreateTime(DateUtils.getNowDate());
        return sensorDataMapper.insertSensorData(sensorData);
    }

    /**
     * 批量新增传感器数据
     * 
     * @param sensorDataList 传感器数据列表
     * @return 结果
     */
    @Override
    public int batchInsertSensorData(List<SensorData> sensorDataList)
    {
        for (SensorData sensorData : sensorDataList)
        {
            sensorData.setCreateTime(DateUtils.getNowDate());
        }
        return sensorDataMapper.batchInsertSensorData(sensorDataList);
    }

    /**
     * 修改传感器数据
     * 
     * @param sensorData 传感器数据
     * @return 结果
     */
    @Override
    public int updateSensorData(SensorData sensorData)
    {
        return sensorDataMapper.updateSensorData(sensorData);
    }

    /**
     * 更新传感器数据处理状态
     * 
     * @param id 传感器数据主键
     * @param handleStatus 处理状态
     * @param handleBy 处理人
     * @param handleRemark 处理备注
     * @return 结果
     */
    @Override
    public int updateSensorDataHandleStatus(Long id, String handleStatus, String handleBy, String handleRemark)
    {
        return sensorDataMapper.updateSensorDataHandleStatus(id, handleStatus, handleBy, handleRemark);
    }

    /**
     * 批量更新传感器数据处理状态
     * 
     * @param ids 传感器数据主键集合
     * @param handleStatus 处理状态
     * @param handleBy 处理人
     * @param handleRemark 处理备注
     * @return 结果
     */
    @Override
    public int batchUpdateSensorDataHandleStatus(Long[] ids, String handleStatus, String handleBy, String handleRemark)
    {
        return sensorDataMapper.batchUpdateSensorDataHandleStatus(ids, handleStatus, handleBy, handleRemark);
    }

    /**
     * 批量删除传感器数据
     * 
     * @param ids 需要删除的传感器数据主键
     * @return 结果
     */
    @Override
    public int deleteSensorDataByIds(Long[] ids)
    {
        return sensorDataMapper.deleteSensorDataByIds(ids);
    }

    /**
     * 删除传感器数据信息
     * 
     * @param id 传感器数据主键
     * @return 结果
     */
    @Override
    public int deleteSensorDataById(Long id)
    {
        return sensorDataMapper.deleteSensorDataById(id);
    }

    /**
     * 根据时间范围删除传感器数据
     * 
     * @param beforeTime 删除此时间之前的数据
     * @return 结果
     */
    @Override
    public int deleteSensorDataByTime(Date beforeTime)
    {
        return sensorDataMapper.deleteSensorDataByTime(beforeTime);
    }

    /**
     * 清理历史传感器数据（保留最近N天的数据）
     * 
     * @param keepDays 保留天数
     * @return 结果
     */
    @Override
    public int cleanHistorySensorData(Integer keepDays)
    {
        return sensorDataMapper.cleanHistorySensorData(keepDays);
    }

    /**
     * 处理实时传感器数据（包含判断和保存）
     * 
     * @param sensorData 传感器数据对象
     * @return 处理结果
     */
    @Override
    public boolean processRealtimeSensorData(SensorData sensorData)
    {
        try
        {
            // 如果没有区域代码，尝试通过坐标获取
            if (StringUtils.isEmpty(sensorData.getRegionCode()) && 
                sensorData.getCoordinateX() != null && sensorData.getCoordinateY() != null)
            {
                // 这里可以集成坐标区域判断服务
                // String regionCode = coordinateRegionService.getRegionByCoordinate(
                //     sensorData.getCoordinateX().doubleValue(), 
                //     sensorData.getCoordinateY().doubleValue(), 
                //     sensorData.getCoordinateZ() != null ? sensorData.getCoordinateZ().doubleValue() : null);
                // sensorData.setRegionCode(regionCode);
            }

            // 获取区域标准配置
            if (StringUtils.isNotEmpty(sensorData.getRegionCode()) && StringUtils.isNotEmpty(sensorData.getSensorType()))
            {
                RegionStandard regionStandard = regionStandardService.selectRegionStandardByCodeAndType(
                    sensorData.getRegionCode(), sensorData.getSensorType());
                if (regionStandard != null)
                {
                    // 使用判断服务进行数据判断
                    sensorDataJudgementService.judge(sensorData, regionStandard);
                }
                else
                {
                    log.warn("未找到区域标准配置: regionCode={}, sensorType={}", 
                        sensorData.getRegionCode(), sensorData.getSensorType());
                }
            }

            // 保存传感器数据
            int result = insertSensorData(sensorData);
            return result > 0;
        }
        catch (Exception e)
        {
            log.error("处理实时传感器数据异常: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 处理实时传感器数据
     * 接收外部传感器数据，进行判断并存储
     * 
     * @param regionCode 区域代码
     * @param sensorType 传感器类型
     * @param value 传感器值
     * @param robotId 机器人ID
     * @param taskId 任务ID
     * @param coordinateX X坐标
     * @param coordinateY Y坐标
     * @param coordinateZ Z坐标
     * @return 处理结果
     */
    @Override
    public SensorData processRealtimeSensorData(String regionCode, String sensorType, Double value, 
                                               String robotId, String taskId, 
                                               Double coordinateX, Double coordinateY, Double coordinateZ)
    {
        try
        {
            // 创建传感器数据对象
            SensorData sensorData = new SensorData();
            sensorData.setRegionCode(regionCode);
            sensorData.setSensorType(sensorType);
            sensorData.setValue(value != null ? BigDecimal.valueOf(value) : null);
            sensorData.setDetectTime(DateUtils.getNowDate());
            sensorData.setRobotId(robotId);
            sensorData.setTaskId(taskId);
            sensorData.setCoordinateX(coordinateX != null ? BigDecimal.valueOf(coordinateX) : null);
            sensorData.setCoordinateY(coordinateY != null ? BigDecimal.valueOf(coordinateY) : null);
            sensorData.setCoordinateZ(coordinateZ != null ? BigDecimal.valueOf(coordinateZ) : null);
            sensorData.setHandleStatus("0"); // 未处理
            sensorData.setCreateTime(DateUtils.getNowDate());

            // 获取区域标准配置
            RegionStandard regionStandard = regionStandardService.selectRegionStandardByCodeAndType(regionCode, sensorType);
            if (regionStandard != null)
            {
                // 使用判断服务进行数据判断
                sensorDataJudgementService.judge(sensorData, regionStandard);
                
                // 记录日志
                log.info("传感器数据处理完成: 区域={}, 类型={}, 值={}, 状态={}, 是否标准={}", 
                        regionCode, sensorType, value, sensorData.getDetectStatus(), sensorData.getIsStandard());
                
                // 如果是异常数据，记录警告日志
                if (sensorData.isAbnormal())
                {
                    log.warn("检测到异常传感器数据: 区域={}, 类型={}, 值={}, 状态={}", 
                            regionCode, sensorType, value, sensorData.getDetectStatus());
                }
            }
            else
            {
                // 没有找到标准配置，设置为未知状态
                sensorData.setDetectStatus("unknown");
                sensorData.setIsStandard("0");
                log.warn("未找到区域标准配置: 区域={}, 传感器类型={}", regionCode, sensorType);
            }

            // 保存到数据库
            insertSensorData(sensorData);
            
            return sensorData;
        }
        catch (Exception e)
        {
            log.error("处理实时传感器数据失败: 区域={}, 类型={}, 值={}", regionCode, sensorType, value, e);
            return null;
        }
    }

    /**
     * 获取传感器数据统计报告
     * 
     * @param regionCode 区域代码（可选）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 统计报告
     */
    @Override
    public String getSensorDataStatisticsReport(String regionCode, Date startTime, Date endTime)
    {
        StringBuilder report = new StringBuilder();
        
        // 总数据量统计
        Long totalCount = countSensorData(regionCode, null, null);
        Long normalCount = countSensorData(regionCode, null, "normal");
        Long warningCount = countSensorData(regionCode, null, "warning");
        Long dangerCount = countSensorData(regionCode, null, "danger");
        
        report.append("传感器数据统计报告\n");
        report.append("统计时间: ").append(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startTime))
              .append(" 至 ").append(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endTime)).append("\n");
        if (StringUtils.isNotEmpty(regionCode))
        {
            report.append("统计区域: ").append(regionCode).append("\n");
        }
        report.append("总数据量: ").append(totalCount).append("\n");
        report.append("正常数据: ").append(normalCount).append("\n");
        report.append("警告数据: ").append(warningCount).append("\n");
        report.append("危险数据: ").append(dangerCount).append("\n");
        
        // 计算百分比
        if (totalCount > 0)
        {
            double normalRate = (normalCount * 100.0) / totalCount;
            double warningRate = (warningCount * 100.0) / totalCount;
            double dangerRate = (dangerCount * 100.0) / totalCount;
            
            report.append("正常率: ").append(String.format("%.2f", normalRate)).append("%\n");
            report.append("警告率: ").append(String.format("%.2f", warningRate)).append("%\n");
            report.append("危险率: ").append(String.format("%.2f", dangerRate)).append("%\n");
        }
        
        return report.toString();
    }

    /**
     * 导出传感器数据
     * 
     * @param sensorData 查询条件
     * @return 传感器数据列表
     */
    @Override
    public List<SensorData> exportSensorData(SensorData sensorData)
    {
        return selectSensorDataList(sensorData);
    }
}